from django.http import JsonResponse, QueryDict
from django.views import View
from kubernetes import client, config
from libs import k8s
import os,json

class service_api(View):

    k8s.load_auth_config()
    core_api = client.CoreV1Api()

    def get(self,request):
        # 查询
        search_key = request.GET.get('query')
        namespace = request.GET.get('namespace')

        data = []  # [{},{},{}]
        try:
            for item in self.core_api.list_namespaced_service(namespace=namespace).items:
                name = item.metadata.name
                namespace = item.metadata.namespace
                labels = item.metadata.labels
                type = item.spec.type
                cluster_ip = item.spec.cluster_ip
                ports = []
                for p in item.spec.ports:  # 不是序列，不能直接返回
                    port_name = p.name
                    port = p.port
                    target_port = p.target_port
                    protocol = p.protocol
                    node_port = ""
                    if type == "NodePort":
                        node_port = p.node_port

                    port = {'port_name': port_name, 'port': port, 'protocol': protocol, 'target_port': target_port,
                            'node_port': node_port}
                    ports.append(port)

                selector = item.spec.selector
                create_time = k8s.timestamp_format(item.metadata.creation_timestamp)

                # 确认是否关联Pod
                endpoint = ""
                for item in self.core_api.list_namespaced_endpoints(namespace=namespace).items:
                    if item.metadata.name == name and item.subsets is None:
                        endpoint = "未关联"
                    else:
                        endpoint = "已关联"

                d = {"name": name, "namespace": namespace, "type": type,
                       "cluster_ip": cluster_ip, "ports": ports, "labels": labels,
                       "selector": selector, "endpoint": endpoint, "create_time": create_time}
                if search_key:
                    if search_key in name:  # 实现模糊匹配
                        data.append(d)
                else:
                    data.append(d)
            code = 200
            msg = "查询成功"
        except Exception as e:
            status = getattr(e, "status")
            if status == 403:  #  400 格式错误，409 资源存在，403 没权限。
                msg = "没有访问权限！"
            else:
                msg = "查询失败！"
            code = 500

        count = len(data)
        # 分页
        page = int(request.GET.get('pageNum', 1))  # 当前第几页
        limit = int(request.GET.get('pageSize',10))   # 当前页的数据数量
        start = (page - 1) * limit  # 获取切片的起始值
        end = page * limit # 获取切片的结束值
        data = data[start:end]

        result = {'code': code, 'msg': msg, 'count': count, 'data': data}
        return JsonResponse(result)
    def post(self,request):
        data = json.loads(request.body.decode("utf-8"))
        name = data["name"]
        namespace = data["namespace"]
        type = data["type"]
        port = int(data["port"])
        taget_port = int(data["target_port"])

        # 处理标签
        labels = {}
        if data["labels"]:
            try:
                for l in data["labels"].split(","):
                    k = l.split("=")[0]
                    v = l.split("=")[1]
                    labels[k] = v
            except Exception as e:
                res = {"code": 500, "msg": "标签格式错误！"}
                return JsonResponse(res)

        try:
            body = client.V1Service(
                api_version="v1",
                kind="Service",
                metadata=client.V1ObjectMeta(
                    name=name,
                ),
                spec=client.V1ServiceSpec(
                    selector=labels,
                    type=type,
                    ports=[client.V1ServicePort(
                        port=port,
                        target_port=taget_port
                    )]
                )
            )
            self.core_api.create_namespaced_service(namespace=namespace, body=body)
            code = 200
            msg = "创建成功"
        except Exception as e:
            status = getattr(e, "status")
            if status == 400:
                msg = "数据格式错误！"
            elif status == 403:
                msg = "没有访问权限！"
            elif status == 409:
                msg = "service已存在！"
            else:
                msg = "服务端处理失败！%s" %e
            code = 500
        result = {'code': code, 'msg': msg}
        return JsonResponse(result)
    def delete(self,request):
        # 删除
        data = json.loads(request.body.decode("utf-8"))
        name = data['name']
        namespace = data.get('namespace')
        try:
            self.core_api.delete_namespaced_service(namespace=namespace, name=name)
            code = 200
            msg = "删除成功"
        except Exception as e:
            status = getattr(e, "status")
            if status == 403:
                msg = "没有访问权限！"
            else:
                msg = "删除失败！%s" %e
            code = 500
        result = {'code': code, 'msg': msg}
        return JsonResponse(result)
    def put(self,request):
        # 更新
        pass


class ingress_api(View):

    k8s.load_auth_config()
    networking_api = client.NetworkingV1Api()
    core_api = client.CoreV1Api()

    def get(self,request):
        data = []
        search_key = request.GET.get("query")
        namespace = request.GET.get("namespace")
        try:
            for item in self.networking_api.list_namespaced_ingress(namespace=namespace).items:
                name = item.metadata.name
                namespace = item.metadata.namespace
                labels = item.metadata.labels
                service = "None"
                http_hosts = "None"
                for h in item.spec.rules:
                    host = h.host
                    path = ("/" if h.http.paths[0].path is None else h.http.paths[0].path)
                    service_name = h.http.paths[0].backend.service.name
                    service_port = h.http.paths[0].backend.service.port.number
                    http_hosts = {'host': host, 'path': path, 'service_name': service_name,
                                  'service_port': service_port}

                https_hosts = "None"
                if item.spec.tls is None:
                    https_hosts = item.spec.tls
                else:
                    for tls in item.spec.tls:
                        host = tls.hosts[0]
                        secret_name = tls.secret_name
                        https_hosts = {'host': host, 'secret_name': secret_name}

                create_time = k8s.timestamp_format(item.metadata.creation_timestamp)

                ing = {"name": name, "namespace": namespace, "labels": labels, "http_hosts": http_hosts,
                       "https_hosts": https_hosts, "service": service, "create_time": create_time}
                # 根据查询关键字返回数据
                if search_key:
                    if search_key in name:
                        data.append(ing)
                else:
                    data.append(ing)
            code = 200
            msg = "查询成功."
        except Exception as e:
            status = getattr(e, 'status')
            if status == 403:
                msg = "没有访问权限！"
            else:
                msg = "查询失败！"
            code = 500

        # 分页
        count = len(data)  # 要在切片之前获取总数

        page = int(request.GET.get('pageNum', 1))  # 当前第几页
        limit = int(request.GET.get('pageSize',10))   # 当前页的数据数量
        # data = data[0:10]
        start = (page - 1) * limit  # 切片的起始值
        end = page * limit  # 切片的末值
        data = data[start:end]  # 返回指定数据范围

        result = {'code': code, 'msg': msg, 'data': data, 'count': count}
        return JsonResponse(result)
        # 创建
    def post(self,request):
        data = json.loads(request.body.decode("utf-8"))
        name = data["name"]
        namespace = data["namespace"]
        domain = data["domain"]
        path = data["path"]
        service_name = data["service"]
        service_port = ''
        for i in self.core_api.list_namespaced_service(namespace=namespace).items:
            svc_name = i.metadata.name
            if svc_name == service_name:
                service_port = i.spec.ports[0].port
        try:
            body = client.V1Ingress(
                api_version="networking.k8s.io/v1",
                kind="Ingress",
                metadata=client.V1ObjectMeta(name=name),
                spec=client.V1IngressSpec(
                    ingress_class_name='nginx',
                    rules=[client.V1IngressRule(
                        host=domain,
                        http=client.V1HTTPIngressRuleValue(
                            paths=[client.V1HTTPIngressPath(
                                path=path,
                                path_type="Prefix",
                                backend=client.V1IngressBackend(
                                    service=client.V1IngressServiceBackend(
                                        port=client.V1ServiceBackendPort(
                                            number=service_port,
                                        ),
                                        name=service_name)
                                )
                            )]
                        )
                    )
                    ]
                )
            )
            self.networking_api.create_namespaced_ingress(namespace=namespace, body=body)
            code = 200
            msg = "创建成功"
        except Exception as e:
            status = getattr(e, "status")
            if status == 400:
                msg = "数据格式错误！"
            elif status == 403:
                msg = "没有访问权限！"
            elif status == 409:
                msg = "ingress已存在！"
            else:
                msg = "服务端处理失败！%s" %e
            code = 500
        result = {'code': code, 'msg': msg}
        return JsonResponse(result)
    def delete(self,request):
        data = json.loads(request.body.decode("utf-8"))
        name = data['name']
        namespace = data.get('namespace')
        try:
            self.networking_api.delete_namespaced_ingress(namespace=namespace, name=name)
            code = 200
            msg = "删除成功."
        except Exception as e:
            status = getattr(e, 'status')
            if status == 403:
                msg = "没有访问权限！"
            else:
                msg = "服务端删除失败！%s" %e
            code = 500

        result = {'code': code, 'msg': msg}
        return JsonResponse(result)